
package combat.dudes.client.gui.threads;

import combat.dudes.client.ClientApp;
import combat.dudes.client.gui.ClientGUI;
import combat.dudes.client.gui.threads.chat.GUIChat;
import combat.dudes.client.gui.threads.info.GUIInfo;
import combat.dudes.client.gui.threads.info.GUIMyStatus;
import combat.dudes.client.gui.threads.map.main.GUIMainMap;
import combat.dudes.client.gui.threads.map.mini.GUIMiniMap;
import combat.dudes.client.gui.threads.shell.GUIShell;
import combat.dudes.client.net.ClientNetworking;
import combat.dudes.client.net.threads.NetChat;
import combat.dudes.client.net.threads.NetSimulation;


/**
 * http://nl.wikibooks.org/wiki/Programmeren_in_Java/Multithreading
 * @author Laurens Andriessen
 * @version 1.0
 */
public class ClientThread extends Thread {

	public enum ClientThreadType {
		// Networking threads
		/** Main network thread */
		NET,

		/** Simulation binding */
		NET_SIM,

		/** Chat server binding */
		NET_CHAT,

		// GUI threads
		/** Main GUI thread */
		GUI,

		/** User interface, builds all screens */
		GUI_SHELL,

		/** Main map, where all physical objects are shown */
		GUI_MAINMAP,

		/** Smaller version of the main map */
		GUI_MINIMAP,

		/** Displaying information on vehicles, orders, etc. */
		GUI_INFO,

		/** Displaying information about the user's own vehicle (position, ammo, health, etc) */
		GUI_MYSTATUS,

		/** Keeps the chat screen updated */
		GUI_CHAT,

		/** Runs clock */
		CLOCK,
	}


	private ClientThreadType type;
	private ClientThreadStatus status;

	public ClientThread(ClientThreadType type) {
		super(type.toString());
		this.type = type;
		this.status = ClientThreadStatus.NEW;
	}

	public void setStatus(ClientThreadStatus status) {
		ClientApp.Log("Thread " + this.type.toString() + " state changed from " + this.status + " to " + status + ".");
		this.status = status;
	}
	public ClientThreadStatus getStatus() {
		return this.status;
	}
	// yield??
	@Override
	public void run() {
		ClientApp.Log("Starting thread " + type.toString());

		for (ClientThread thread : ClientGUI.gui_threads_waiting)
			if (this == thread) doWait(this.type);

		switch(type) {
			case NET:
				new ClientNetworking();
				break;
			case NET_SIM:
				new NetSimulation();
				break;
			case NET_CHAT:
				new NetChat();
				break;

			case GUI:
				new ClientGUI();
				break;
			case GUI_SHELL:
				new GUIShell();
				break;
			case GUI_MAINMAP:
				new GUIMainMap();
				break;
			case GUI_MINIMAP:
				new GUIMiniMap();
				break;
			case GUI_INFO:
				new GUIInfo();
				break;
			case GUI_MYSTATUS:
				new GUIMyStatus();
				break;
			case GUI_CHAT:
				new GUIChat();
				break;

			case CLOCK:
				new Clock();
				break;
		}
	}
	private void doWait(ClientThreadType type) {
		// Wait 'till GO signal is given by the GUI_SHELL thread
		synchronized (this) {
			try {
				this.setStatus(ClientThreadStatus.WAITING);
				ClientApp.Log("Waiting...");
				this.wait();
			} catch (Exception e) {
				ClientApp.onError("wait() interrupted?!", e, false);
			}
			this.setStatus(ClientThreadStatus.WORKING);
		}
		ClientApp.Log("Done waiting! Starting...");
	}
}
